import { isNil, forEach, getVariType } from "../libs/utils";

class BaseTable{
    constructor(opts = {}){
        this.tableData = opts.tableData;
        this.colsIns = opts.colsIns;
        this.rowsIns = opts.rowsIns;

        this.lastView = {
            headRows: 0,
            bodyRows: 0,
            cols: 0
        }

        this.table = document.createElement('table');
    }
    render(start = {}, end = {}, fixed = {}){
        let colStart = start.col;
        let colEnd = end.col;
        let rowStart = start.row;
        let rowEnd = end.row;

        let fixedRowsTop = fixed.top || 0;

    }
    render1(start = {}, end = {}){
        let me = this;
        let colStart = start.col;
        let colEnd = end.col;
        let rowStart = start.row;
        let rowEnd = end.row;

        let lastColStart = this.lastInfo.colStart;
        let lastColEnd = this.lastInfo.colEnd;
        let lastRowStart = this.lastInfo.rowStart;
        let lastRowEnd = this.lastInfo.rowEnd;

        let dataColStart = Math.min(colStart, lastColStart);
        let dataColEnd = Math.max(colEnd, lastColEnd);
        let dataRowStart = Math.min(rowStart, lastRowStart);
        let dataRowEnd = Math.max(rowEnd, lastRowEnd);

        let dataRange = this.tableData.getRange({
            col: dataColStart,
            row: dataRowStart
        }, {
            col: dataColEnd,
            row: dataRowEnd
        });

        let cols = this.colsIns.getData(dataColStart, dataColEnd);
        let rows = this.rowsIns.getData(dataRowStart, dataRowEnd);

        let vtrs = [];
        forEach(dataRange, function(rowData, i){
            let rowInfo = rows[i];
            let rowIndex = rowInfo.index;
            let vtr = getVirtualTrStruct();
            if(rowIndex > rowEnd || rowIndex < rowStart){
                vtr.isRemove = true;
            }else if(
                (rowIndex <= rowEnd && rowIndex >= rowStart) && 
                (rowIndex < lastRowStart || rowIndex > lastRowEnd)
            ){
                vtr.isAppend = true;
            }

            if(!rowInfo._$el){
                rowInfo._$el = me.createTr(rowInfo);
            }
            vtr.row = rowInfo;

            forEach(rowData, function(cell){
                let vtd = getVirtualTdStruct();
                if(!cell._$el){
                    cell._$el = me.createTd(cell);
                }
                let colIndex = cell.colIndex;
                if(colIndex > colEnd || colIndex < colStart){
                    vtd.isRemove = true;
                }else if(
                    (colIndex <= colEnd && colIndex >= colStart) &&
                    (colIndex < lastColStart || colIndex > lastColEnd)
                ){
                    vtd.isAppend = true;
                }
                
                vtd.td = cell;
                vtr.tds.push(vtd);
            })


            vtrs.push(vtr);
        });

        forEach(vtrs, function(vtr){
            let $tr = vtr.row._$el;
            let parentNode = $tr.parentNode;
            if(vtr.isRemove){
                parentNode && parentNode.removeChild($tr);
            }else{
                forEach(vtr.tds, function(vtd){
                    let $td = vtd.td._$el;
                    if(vtd.isRemove){
                        $tr.removeChild($td);
                    }else if(vtd.isAppend){
                    }
                })
            }
        })
    }

    _render(start = {}, end = {}){
        

        // appendRows
        let appendRows = [];
        for(let i = lastRowEnd; i <= rowEnd; i++){
            let tr = this.createTr(i);
            let tds = this.getTds(i, colStart, colEnd);
            forEach(tds, function(td){
                tr.appendChild(td);
            });
            appendRows.push(tr);
        }

        // unshiftRows
        let unshiftRows = [];
        for(let i = lastRowStart; i >= rowStart; i++){
            let tr = this.createTr(i);
            let tds = this.getTds(i, colStart, colEnd);
            forEach(tds, function(td){
                tr.appendChild(td);
            });
            unshiftRows.push(tr);
        }

        // removeRows
        let removeRows = [];
        for(let i = lastRowStart; i < rowStart; i++){
            let rowInfo = this.rowsIns.getItem(i);
            removeRows.push(rowInfo._$el);
        }
        for(let i = rowEnd + 1; i <= lastRowEnd; i++){
            let rowInfo = this.rowsIns.getItem(i);
            removeRows.push(rowInfo._$el);
        }

        // appendTds
        let changedRows = [];
    }

    getTds(rowIndex, colStart, colEnd){
        let me = this;
        let rowData = this.tableData.getRow(rowIndex, colStart, colEnd);
        let tds = [];
        forEach(rowData, function(cell){
            let td = cell._$el;
            if(!td){
                td = me.createTd(cell);
                cell._$el = td;
            }
            tds.push(td);
        })
        return tds;
    }

    createTr(rowIndex){
        let rowInfo = null;
        if(getVariType(rowIndex) === 'number'){
            rowInfo = this.rowsIns.getItem(rowIndex);
        }else{
            rowInfo = rowIndex;
        }
        let tr = document.createElement('tr');
        tr.className = getRowClass(rowInfo);
        tr.style = rowInfo.style || '';
        if(!isNil(rowInfo.size)){
            tr.style.height = `${rowInfo.size}px`;
        }
        tr.dataset.index = rowInfo.index;

        return tr;
    }

    createTd(cell){
        let tag = this.getTag(cell.rowIndex, cell.colIndex);
        let child = document.createElement(tag);
        child.dataset.row = cell.rowIndex;
        child.dataset.col = cell.colIndex;
        child.rowspan = cell.rowspan;
        child.colspan = cell.colspan;
        child.style = cell.style || '';
        child.className = getThTdClass(cell);
        child.innerText = cell.text;

        return child;
    }

    getTag(rowIndex, colIndex){
        let rowInfo = this.rowsIns.getItem(rowIndex);
        let colInfo = this.colsIns.getItem(colIndex);
        if(rowInfo.isHeader || colInfo.isHeader){
            return 'th';
        }
        return 'td';
    }
}

function getRowClass(rowInfo){
    let index = rowInfo.index;
    let defClass = index % 2 ? 'even' : 'odd';
    let customClass = rowInfo.classList ? rowInfo.classList.join(' ') : '';
    return defClass + ' ' + customClass;
}

function getThTdClass(info){
    let className = '';
    if(info.classList){
        className = info.classList.join(' ');
    }

    return className;
}

function getVirtualTrStruct(){
    return {
        isRemove: false,
        isAppend: false,

        tds: [],

        row: null
    }
}

function getVirtualTdStruct(){
    return {
        isRemove: false,
        isAppend: false,

        td: null
    }
}

export default BaseTable;